package tmi.li.testapp;



import android.graphics.Canvas;
import android.view.SurfaceHolder;


public class CanvasThread extends Thread {
    private SurfaceHolder _surfaceHolder;
    private LayoutEditor _panel;
    private boolean _run = false;

    // desired fps
    private final static int    MAX_FPS = 44;
    // maximum number of frames to be skipped
    private final static int    MAX_FRAME_SKIPS = 5;
    // the frame period
    private final static int    FRAME_PERIOD = 1000 / MAX_FPS;
    // Stuff for statistics
    //private DecimalFormat df = new DecimalFormat("0.##");
    // we'll be reading the stats every second
    private final static int    STAT_INTERVAL = 1000; //ms
    // the average will be calculated by storing
    // the last n FPSs
    private final static int    FPS_HISTORY_NR = 10;
    // the status time counter
    private long statusIntervalTimer    = 0l;
    // number of frames skipped since the game started
    private long totalFramesSkipped         = 0l;
    // number of frames skipped in a store cycle (1 sec)
    private long framesSkippedPerStatCycle  = 0l;
    // number of rendered frames in an interval
    private int frameCountPerStatCycle = 0;
    private long totalFrameCount = 0l;
    // the last FPS values
    private double  fpsStore[];
    // the number of times the stat has been read
    private long    statsCount = 0;
    // the average FPS since the game started
    private double  averageFps = 0.0;


    
    public CanvasThread(SurfaceHolder surfaceHolder, LayoutEditor panel) {
        _surfaceHolder = surfaceHolder;
        _panel = panel;

    }
    
    public SurfaceHolder getSurfaceHolder() {
        return _surfaceHolder;
    }
 
    public void setRunning(boolean run) {
        _run = run;
    }
 
    @Override
    public void run() {
        Canvas c;
        
        initTimingElements();

        
        long beginTime;     // the time when the cycle begun
        long timeDiff;      // the time it took for the cycle to execute
        int sleepTime;      // ms to sleep (<0 if we're behind)
        int framesSkipped;  // number of frames being skipped 

        
        while (_run) {
            c = null;
            try {
                c = _surfaceHolder.lockCanvas(null);
                
                synchronized (_surfaceHolder) {
                	
                	beginTime = System.currentTimeMillis();
                	framesSkipped = 0;
             
                    _panel.onDraw(c);
                    _panel.update();
                    
                    timeDiff = System.currentTimeMillis() - beginTime;
                    sleepTime = (int)(FRAME_PERIOD - timeDiff);

                    if (sleepTime > 0) {
                        try { Thread.sleep(sleepTime); } catch (InterruptedException e) {}
                    }
                    
                    while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
                    	_panel.update();
                    	sleepTime += FRAME_PERIOD;
                    	framesSkipped++;
                    }
                    framesSkippedPerStatCycle += framesSkipped;
                    storeStats();
                }
                
                
            } catch(Exception e) {
            	
            } finally {
                // do this in a finally so that if an exception is thrown
                // during the above, we don't leave the Surface in an
                // inconsistent state
                if (c != null) {
                    _surfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }
    
    private void storeStats() {
    	frameCountPerStatCycle++;
    	totalFrameCount++;
    	// assuming that the sleep works each call to storeStats
    	// happens at 1000/FPS so we just add it up
    	statusIntervalTimer += FRAME_PERIOD;
    	if (statusIntervalTimer >= STAT_INTERVAL) {    	// calculate the actual frames pers status check interval
    		double actualFps = (double)(frameCountPerStatCycle / (STAT_INTERVAL / 1000));
    		//stores the latest fps in the array
    		fpsStore[(int) statsCount % FPS_HISTORY_NR] = actualFps;
    	    // increase the number of times statistics was calculated
    		statsCount++;
    		double totalFps = 0.0;
    		// sum up the stored fps values
    		for (int i = 0; i < FPS_HISTORY_NR; i++) {
    			totalFps += fpsStore[i];
    		}
    		// obtain the average
    		if (statsCount < FPS_HISTORY_NR) {  // in case of the first 10 triggers
    			averageFps = totalFps / statsCount;
    		} else {
    			averageFps = totalFps / FPS_HISTORY_NR;
    		}
    		// saving the number of total frames skipped
    		totalFramesSkipped += framesSkippedPerStatCycle;
    		// resetting the counters after a status record (1 sec)
    		framesSkippedPerStatCycle = 0;
    		statusIntervalTimer = 0;
    		frameCountPerStatCycle = 0;
    		//_panel.world.set_fps((int)averageFps);
    	}
    }

    private void initTimingElements() {
    	// initialise timing elements
    	fpsStore = new double[FPS_HISTORY_NR];
    	for (int i = 0; i < FPS_HISTORY_NR; i++) {
    		fpsStore[i] = 0.0;
    	}

    }  
    
    
}